#pragma once

#include "geometry.h"

#include <vector>

namespace kp {

	struct ImageFilm {
		Pixel* data = nullptr;
		size_t width, height;
		const size_t channel = 3;

		ImageFilm(size_t w, size_t h)
			:width(w), height(h) {
			data = new Pixel[width * height * channel];
		}

		void free() {
			delete[] data;
		}

	};

	struct Film {
		std::vector<Spectrum> frags;
		Vec<size_t, 2> size;

		Film(size_t w, size_t h)
			:size(w, h)
		{
			frags.resize(w * h);
		}

		operator ImageFilm() {
			ImageFilm ret(size.w, size.h);
			for (int y = 0; y < size.h; y++) {
				for (int x = 0; x < size.w; x++) {
					ret.data[x * ret.channel + y * ret.width * ret.channel] = to_pixel(frags[x + y * size.w][0]);
					ret.data[x * ret.channel + y * ret.width * ret.channel + 1] = to_pixel(frags[x + y * size.w][1]);
					ret.data[x * ret.channel + y * ret.width * ret.channel + 2] = to_pixel(frags[x + y * size.w][2]);
				}
			}
			return ret;
		}
	
	private:
		static float gamma(float x, float k = Invgamma) {
			return std::pow(std::clamp(x, 0.0f, 1.0f), k);
		}

		static Pixel to_pixel(float x) {
			return std::max<Pixel>(0, std::min<Pixel>(255, std::lroundf(gamma(x) * 255)));
		}

	};

}